/**
 @file ctc_app_packet_cli.c

 @author  Copyright (C) 2012 Centec Networks Inc.  All rights reserved.

 @date 2012-11-25

 @version v2.0

 This file define packet sample CLI functions

*/

#include "api/include/ctc_api.h"
#include "ctc_cli.h"
#include "ctc_app_packet.h"
#include "ctc_app_eunit.h"
#include "ctc_cli_common.h"
#include "ctc_app.h"
#include "ctc_app_warmboot.h"
#include "ctc_app_flow_recorder.h"
#include "common/include/ctc_pmem.h"

extern int32 ctc_usw_dkit_init(uint8 lchip);
extern int32 ctc_usw_dkit_deinit(uint8 lchip);
extern int32
ctc_app_isr_init(void);

extern int32 ctc_app_isr_init(void);
extern int32 ctcs_app_isr_init(uint8 lchip);
extern int32 ctc_app_read_ftm_profile(const int8* file_name,
                     ctc_ftm_profile_info_t* profile_info);
extern ctc_init_cfg_t* g_init_cfg;
extern int32 ctc_dkit_cli_chip_special_deinit(uint8 lchip);
extern int32 ctc_dkit_cli_chip_special_init(uint8 lchip);
extern ctc_chip_special_callback_fun_t g_chip_special_cli[MAX_CTC_CHIP_TYPE];


CTC_CLI(ctc_cli_app_packet_show,
        ctc_cli_app_packet_show_cmd,
        "show app packet stats",
        CTC_CLI_SHOW_STR,
        CTC_CLI_APP_M_STR,
        "Packet",
        "Stats")
{
    ctc_app_packet_sample_show();
    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_packet_print_rx,
        ctc_cli_app_packet_print_rx_cmd,
        "app packet cpu-rx-print (on|off)",
        CTC_CLI_APP_M_STR,
        "Packet",
        "Print CPU RX packet",
        "On",
        "Off")
{
    uint32 enable = FALSE;
    int32 ret = 0;

    if (0 == sal_strcmp(argv[0], "on"))
    {
        enable = TRUE;
    }
    else
    {
        enable = FALSE;
    }

    ret = ctc_app_packet_sample_set_rx_print_en(enable);
    if (ret < 0)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_packet_create_socket,
        ctc_cli_app_packet_create_socket_cmd,
        "app packet create eth-socket ifid IFID",
        CTC_CLI_APP_M_STR,
        "Packet",
        "Create",
        "Socket",
        "Eth interface",
        "Interface Id")
{
    uint16 if_id = 0;
    int32 ret = 0;

    CTC_CLI_GET_UINT16_RANGE("if-id", if_id, argv[0], 0, CTC_MAX_UINT16_VALUE);

    ret = ctc_app_packet_sample_eth_open_raw_socket(if_id);
    if (ret < 0)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_packet_destroy_socket,
        ctc_cli_app_packet_destroy_socket_cmd,
        "app packet destroy eth-socket",
        CTC_CLI_APP_M_STR,
        "Packet",
        "Destroy",
        "Socket")
{
    int32 ret = 0;
    ret = ctc_app_packet_sample_eth_close_raw_socket();
     if (ret < 0)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CLI_SUCCESS;
}

#ifdef _SAL_LINUX_UM
extern int32 ctc_app_packet_netif_rx(char* eth_name, uint8 rebind);
extern int32 ctc_app_packet_netif_tx(char* eth_name, uint8 rebind, uint8 *tx_pkt, uint16 pkt_len);
CTC_CLI(ctc_cli_app_packet_netif_rx_tx,
        ctc_cli_app_packet_netif_rx_tx_cmd,
        "app packet netif (rx|tx) NAME {rebind|with-brg-hdr dest-port DEST_GPORT|} (lchip LCHIP|)",
        CTC_CLI_APP_M_STR,
        "Packet",
        "Netif",
        "Receive",
        "Send",
        "Netif Name",
        "Rebind new socket",
        "Tx with bridge header",
        "Destination global port ID",
        CTC_CLI_GPORT_ID_DESC,
        "lchip",
        "LCHIP")
{
    int32 ret = CTC_E_NONE;
    uint8 index = 0;
    uint8 is_rx = 0;
    uint8 is_rebind = 0;
    uint8 tx_with_brg_hdr = 0;
    char name[32];
    ctc_pkt_tx_t pkt_tx;
    ctc_pkt_tx_t* p_pkt_tx = &pkt_tx;
    ctc_pkt_info_t* p_tx_info = &(p_pkt_tx->tx_info);
    ctc_pkt_skb_t* p_skb = &(p_pkt_tx->skb);
    uint32 capability[CTC_GLOBAL_CAPABILITY_MAX] = {0};

    static uint8 pkt_buf_uc[CTC_PKT_MTU] = {
        0x00, 0x1F, 0xFE, 0xAF, 0xAD, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x81, 0x00, 0x00, 0x0A,
        0x08, 0x00, 0x45, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x11, 0xB8, 0xAF, 0x01, 0x00,
        0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x35, 0x00, 0x2A, 0xFC, 0x26, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    sal_memset(&pkt_tx, 0, sizeof(pkt_tx));
    p_tx_info->ttl = 1;

    index = CTC_CLI_GET_SPECIFIC_INDEX("rx", 0);
    if (0xFF != index)
    {
        is_rx = 1;
    }
    sal_memcpy(name, argv[1], CTC_PKT_MAX_NETIF_NAME_LEN);

    index = CTC_CLI_GET_ARGC_INDEX("rebind");
    if (0xFF != index)
    {
        is_rebind = 1;
    }

    index = CTC_CLI_GET_ARGC_INDEX("with-brg-hdr");
    if (0xFF != index)
    {
        tx_with_brg_hdr = 1;
    }
    index = CTC_CLI_GET_ARGC_INDEX("dest-port");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32("dest-gport", p_tx_info->dest_gport, argv[index + 1]);
    }

    index = CTC_CLI_GET_ARGC_INDEX("lchip");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32("lchip", p_pkt_tx->lchip, argv[index + 1]);
    }
    
    if (is_rx)
    {
        ret = ctc_app_packet_netif_rx(name, is_rebind);
    }
    else
    {
        if(tx_with_brg_hdr)
        {
            if(g_ctcs_api_en)
            {
                ret = ctcs_global_ctl_get(g_api_ldev, CTC_GLOBAL_CHIP_CAPABILITY, capability);
            }
            else
            {
                ret = ctc_global_ctl_get(CTC_GLOBAL_CHIP_CAPABILITY, capability);
            }
            if (ret < 0)
            {
                ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
                return CLI_ERROR;
            }

            ret = ctc_packet_skb_init(p_skb);
            if (ret < 0)
            {
                 return CLI_ERROR;
            }

            /*move head pointer*/
            p_skb->head += (CTC_PKT_HDR_ROOM-capability[CTC_GLOBAL_CAPABILITY_PKT_HDR_LEN]);

            if(g_ctcs_api_en)
            {
                ret = ctcs_packet_encap(g_api_ldev, p_pkt_tx);
            }
            else
            {
                ret = ctc_packet_encap(p_pkt_tx);
            }
            /*copy packet*/
            sal_memcpy(ctc_packet_skb_put(p_skb, 80), pkt_buf_uc, 80);
        }

        ret = ret ? ret : ctc_app_packet_netif_tx(name, is_rebind, tx_with_brg_hdr ? p_skb->head:pkt_buf_uc, \
                                tx_with_brg_hdr?80+capability[CTC_GLOBAL_CAPABILITY_PKT_HDR_LEN]:80);
    }
    if (ret < 0)
    {
        ctc_cli_out("netif rx error, ret = %d\n", ret);
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}
#endif

CTC_CLI(ctc_cli_app_debug_on,
        ctc_cli_app_debug_on_cmd,
        "debug app app (debug-level {func|param|info|error} |)",
        CTC_CLI_DEBUG_STR,
        "App",
        CTC_CLI_APP_M_STR,
        CTC_CLI_DEBUG_LEVEL_STR,
        CTC_CLI_DEBUG_LEVEL_FUNC,
        CTC_CLI_DEBUG_LEVEL_PARAM,
        CTC_CLI_DEBUG_LEVEL_INFO,
        CTC_CLI_DEBUG_LEVEL_ERROR)
{

    uint32 typeenum = 0;
    uint8 level = CTC_DEBUG_LEVEL_INFO | CTC_DEBUG_LEVEL_FUNC | CTC_DEBUG_LEVEL_PARAM | CTC_DEBUG_LEVEL_ERROR;
    uint8 index = 0;

    index = CTC_CLI_GET_ARGC_INDEX("debug-level");
    if (index != 0xFF)
    {
        level = CTC_DEBUG_LEVEL_NONE;
        index = CTC_CLI_GET_ARGC_INDEX("func");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_FUNC;
        }

        index = CTC_CLI_GET_ARGC_INDEX("param");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_PARAM;
        }

        index = CTC_CLI_GET_ARGC_INDEX("info");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_INFO;
        }

        index = CTC_CLI_GET_ARGC_INDEX("error");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_ERROR;
        }
    }

    typeenum = APP_SMP;

    ctc_debug_set_flag("app", "app", typeenum, level, TRUE);

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_debug_off,
        ctc_cli_app_debug_off_cmd,
        "no debug app app",
        CTC_CLI_NO_STR,
        CTC_CLI_DEBUG_STR,
        "App",
        CTC_CLI_APP_M_STR)
{
    uint32 typeenum = APP_SMP;
    uint8 level = 0;

    ctc_debug_set_flag("app", "app", typeenum, level, FALSE);

    return CLI_SUCCESS;
}

extern int32 ctc_app_parse_config(uint8 lchip, ctc_init_cfg_t * p_init_config);
extern int32 ctc_app_free_init_param(ctc_init_cfg_t* p_init_config);
extern void ctc_app_wb_pmem_init(uint8 lchip, ctc_wb_api_t* wb_api, ctc_init_cfg_t *p_init_config);
extern void ctc_app_sdb_pmem_init(uint8 lchip, ctc_init_cfg_t *p_init_config, ctc_wb_api_t* wb_api);

CTC_CLI(ctc_cli_app_module_init,
        ctc_cli_app_module_init_cmd,
        "app sdk init {wb-reloading (db|) | ldev LDEV | add-dev | }",
        CTC_CLI_APP_M_STR,
        "SDK",
        "Init",
        "Warmboot reloading status",
        "Wb DB mode",
        "Ldev",
        "Ldev ID",
        "Add dal dev")
{
    int32 ret = 0;
    uint8 index = 0;
    uint8 ldev = g_api_ldev;
    ctc_init_cfg_t init_config;
    ctc_wb_api_t wb_api;
    uint8 chip_type = 0;
#if defined(DUET2) || defined(TSINGMA) || defined(TSINGMA_MX) || defined(ARCTIC)
    uint8 loop_dev = 0;
#endif
    index = CTC_CLI_GET_ARGC_INDEX("ldev");
    if (index != 0xFF)
    {
        CTC_CLI_GET_UINT8("ldev", ldev, argv[index + 1]);
    }




    if(ldev >= g_ctc_app_master.lchip_num)
    {
        CTC_APP_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Invalid chip id:%s@%d \n",  __FUNCTION__, __LINE__);
        return CTC_E_INVALID_CHIP_ID;
    }

    sal_memset(&wb_api, 0, sizeof(ctc_wb_api_t));
    sal_memset(&init_config, 0, sizeof(ctc_init_cfg_t));

    index = CTC_CLI_GET_ARGC_INDEX("wb-reloading");
    if (index != 0xFF)
    {
        g_ctc_app_master.wb_enable = 1;
        g_ctc_app_master.wb_reloading = 1;
    }

    /* init sal module */
    ret = sal_init();
    if (ret != 0)
    {
        CTC_APP_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"sal_init failed:%s@%d \n",  __FUNCTION__, __LINE__);
        goto EXIT;
    }
    
    ret = ctc_app_parse_config(ldev, &init_config);
    if (ret != 0)
    {
        CTC_APP_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "ctc_app_get_config failed:%s@%d \n",  __FUNCTION__, __LINE__);
        goto EXIT;
    }
    

   
    wb_api.mode  = 1;
    index = CTC_CLI_GET_ARGC_INDEX("db");
    if (index != 0xFF)
    {
        wb_api.mode  = 0;
    }

    ctc_app_wb_pmem_init(ldev, &wb_api, &init_config);
   
    /* init pmem for sdb */
    ctc_app_sdb_pmem_init(ldev, &init_config, &wb_api);
      
    if (ret != 0)       
    {        
          CTC_APP_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "ctc_wb_init failed:%s@%d \n",  __FUNCTION__, __LINE__);          
          goto EXIT;    
    }
           
    g_ctc_app_master.lchip_num = init_config.local_chip_num;
    sal_memcpy(g_ctc_app_master.gchip_id, init_config.gchip, sizeof(uint8)*CTC_MAX_LOCAL_DEV_NUM);     
   
    if (g_ctc_app_master.ctcs_api_en)
    {
        ret = ctcs_sdk_init(ldev, &init_config);
#if defined(DUET2) || defined(TSINGMA) || defined(TSINGMA_MX) || defined(ARCTIC)
        ret = ret? ret: ctc_usw_dkit_init(CTC_MAP_LCHIP(ldev));
#endif
    }
    else
    {
        ret = ctc_sdk_init(&init_config);
#if defined(DUET2) || defined(TSINGMA) || defined(TSINGMA_MX) || defined(ARCTIC)
        for (loop_dev = 0;loop_dev< g_ctc_app_master.lchip_num; loop_dev++)
        {
            ctc_usw_dkit_init(CTC_MAP_LCHIP(loop_dev));
        }
#endif
    }
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    if (g_ctc_app_master.ctcs_api_en)
    {
        ret = ctcs_app_isr_init(ldev);
    }
    else
    {
        ret = ctc_app_isr_init();
    }
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    if (g_ctcs_api_en && ldev == g_api_ldev)
    {
        chip_type = ctcs_get_chip_type(ldev);
        ctc_dkit_cli_chip_special_init(ldev);
        (*g_chip_special_cli[chip_type].chip_special_cli_init)();
    }

EXIT:
    ctc_app_free_init_param(&init_config);

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_module_deinit,
        ctc_cli_app_module_deinit_cmd,
        "app sdk deinit {rm-dev | ldev LDEV |}",
        CTC_CLI_APP_M_STR,
        "SDK",
        "Deinit",
        "Remove device",
        "Ldev",
        "Ldev ID")
{
    int32 ret = 0;
	uint8 chip_type_old = 0;
	#if defined(DUET2) || defined(TSINGMA) || defined(TSINGMA_MX) || defined(ARCTIC)
    uint8 lchip = 0, lchip_num = 0;
	#endif
    uint8 index = 0;
    uint8 ldev = g_api_ldev;

    index = CTC_CLI_GET_ARGC_INDEX("ldev");
    if (index != 0xFF)
    {
        CTC_CLI_GET_UINT8("ldev", ldev, argv[index + 1]);
    }

    if (g_ctcs_api_en && ldev == g_api_ldev)
    {
        chip_type_old = ctcs_get_chip_type(ldev);
        ctc_dkit_cli_chip_special_deinit(g_api_lchip);
        if(g_chip_special_cli[chip_type_old].chip_special_cli_deinit)
        {
            (*g_chip_special_cli[chip_type_old].chip_special_cli_deinit)();
        }
    }
    
    if(CTC_MAP_LDEV(g_api_lchip) >= g_ctc_app_master.lchip_num)
    {
        CTC_APP_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Invalid chip id:%s@%d \n",  __FUNCTION__, __LINE__);
        return CTC_E_INVALID_CHIP_ID;
    }

    if (g_ctc_app_master.ctcs_api_en)
    {
#if defined(DUET2) || defined(TSINGMA) || defined(TSINGMA_MX) || defined(ARCTIC)
        ctc_usw_dkit_deinit(CTC_MAP_LCHIP(ldev));
#endif
        ret = ctcs_sdk_deinit(ldev);
    }
    else
    {
#if defined(DUET2) || defined(TSINGMA) || defined(TSINGMA_MX) || defined(ARCTIC)
        ctc_get_local_chip_num(&lchip_num);
        for (lchip = 0; lchip < lchip_num; lchip++)
        {
            ctc_usw_dkit_deinit(CTC_MAP_LCHIP(lchip));
        }
#endif
        ret = ctc_sdk_deinit();
    }
#if defined(DUET2) || defined(TSINGMA) || defined(TSINGMA_MX) || defined(ARCTIC)
	ctc_pmem_deinit(ldev);
    g_ctc_app_master.wb_reloading = 0;
#endif

    if (ret < 0)
    {
        ctc_cli_out("%% deinit fail\n");
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_change_mem_profile,
    ctc_cli_app_change_mem_profile_cmd,
    "app ftm change-profile FILENAME (recover-en |)(lchip LCHIP|)",
    CTC_CLI_APP_M_STR,
    "Ftm",
    "Change memory profile",
    "File name",
    "Recover enable",
    "Lchip",
    "Lchip ID")
{

    uint8 lchip = 0;
    int32 ret = 0;
    uint8 index = 0;

    ctc_ftm_profile_info_t new_profile;
    ctc_ftm_change_profile_t profile;

    sal_memset(&new_profile, 0, sizeof(new_profile));
    sal_memset(&profile, 0, sizeof(profile));
    new_profile.key_info = (ctc_ftm_key_info_t*)mem_malloc(MEM_APP_MODULE, sizeof(ctc_ftm_key_info_t)*CTC_FTM_KEY_TYPE_MAX);
    new_profile.tbl_info = (ctc_ftm_tbl_info_t*)mem_malloc(MEM_APP_MODULE, sizeof(ctc_ftm_tbl_info_t)*CTC_FTM_TBL_TYPE_MAX);
    if(NULL==new_profile.key_info||NULL==  new_profile.tbl_info)
    {
    	  ret =  CLI_ERROR;
        goto end_0;
    }
    sal_memset(new_profile.key_info, 0, sizeof(ctc_ftm_key_info_t)*CTC_FTM_KEY_TYPE_MAX);
    sal_memset(new_profile.tbl_info, 0, sizeof(ctc_ftm_tbl_info_t)*CTC_FTM_TBL_TYPE_MAX);
    ret = ctc_app_read_ftm_profile((const int8*)argv[0], &new_profile);
    if(ret == CTC_E_NONE)
    {
        new_profile.profile_type = CTC_FTM_PROFILE_USER_DEFINE;
    }
    else
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return ret;
    }

    profile.new_profile = &new_profile;
    index = CTC_CLI_GET_ARGC_INDEX("recover-en");
    if (index != 0xFF)
    {
        profile.recover_en = 1;
    }

    index = CTC_CLI_GET_ARGC_INDEX("lchip");
    if (index != 0xFF)
    {
        CTC_CLI_GET_UINT8("lchip", lchip, argv[index + 1]);
    }

    if (g_ctc_app_master.ctcs_api_en)
    {
        ret = ctcs_sdk_change_mem_profile(lchip, &profile);
    }
    else
    {
        ret = ctc_sdk_change_mem_profile(&profile);
    }
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        ret =  CLI_ERROR;
        goto end_0;
    }

    if(profile.change_mode > 1)
    {
        if (g_ctc_app_master.ctcs_api_en)
        {
            ret = ctcs_app_isr_init(lchip);
        }
        else
        {
            ret = ctc_app_isr_init();
        }
        if (ret)
        {
            ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
            return CLI_ERROR;
        }
    }

end_0:
    if(new_profile.key_info)
    {
        mem_free(new_profile.key_info);
    }

    if(new_profile.tbl_info)
    {
        mem_free(new_profile.tbl_info);
    }
    return ret;
}

#ifdef CTC_PUMP
#include "ctc_pump_app.h"

CTC_CLI(ctc_cli_app_pump_init_deinit,
        ctc_cli_app_pump_init_deinit_cmd,
        "app pump (init | deinit) (lchip CHIPID|)",
        CTC_CLI_APP_M_STR,
        "Pump",
        "Init",
        "Deinit",
        "Local chip",
        "Local chip ID")
{
    int32 ret = 0;
    uint8 index = 0;
    uint8 lchip = 0;

    index = CTC_CLI_GET_ARGC_INDEX("lchip");
    if (index != 0xFF)
    {
        CTC_CLI_GET_UINT8("lchip", lchip, argv[index + 1]);
    }
    if(lchip >= g_ctc_app_master.lchip_num)
    {
        CTC_APP_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Invalid chip id:%s@%d \n",  __FUNCTION__, __LINE__);
        return CTC_E_INVALID_CHIP_ID;
    }
    if (CLI_CLI_STR_EQUAL("init", 0))
    {
        ret = ctc_pump_app_init(lchip);
    }
    else
    {
        ret = ctc_pump_app_deinit(lchip);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% pump %s fail\n", argv[0]);
        return CLI_ERROR;
    }
    return ret;
}

#endif
#ifdef CTC_APP_FLOW_RECORDER
CTC_CLI(ctc_cli_app_fr_init,
    ctc_cli_app_fr_init_cmd,
    "app flow-recorder init enable-ipfix-level LEVEL {resolve-conflict-en LEVEL1|queue-drop-pkt-stats-en|}",
    CTC_CLI_APP_M_STR,
    "FLow recorder",
    "init",
    "enable ipfix level",
    "Acl level",
    "resolve-conflict-en",
    "ACL level",
    "queue drop packet stats en")

{
    int32 ret = 0;
    uint8 index = 0;

    ctc_app_flow_recorder_init_param_t init_param;
    sal_memset(&init_param, 0, sizeof(init_param));

    CTC_CLI_GET_UINT8("acl level", init_param.enable_ipfix_level, argv[0]);

    index = CTC_CLI_GET_ARGC_INDEX("resolve-conflict-en");
    if(index != 0xFF)
    {
        init_param.resolve_conflict_en = 1;
        CTC_CLI_GET_UINT8("acl level", init_param.resolve_conflict_level, argv[index+1]);
    }

    index = CTC_CLI_GET_ARGC_INDEX("queue-drop-pkt-stats-en");
    if(index != 0xFF)
    {
        init_param.queue_drop_stats_en = 1;
    }

    ret = ctc_app_flow_recorder_init(&init_param);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CTC_E_NONE;
}

CTC_CLI(ctc_cli_app_fr_deinit,
    ctc_cli_app_fr_deinit_cmd,
    "app flow-recorder deinit",
    CTC_CLI_APP_M_STR,
    "FLow recorder",
    "deinit")

{
    int32 ret = 0;
    ret = ctc_app_flow_recorder_deinit();
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CTC_E_NONE;
}
CTC_CLI(ctc_cli_app_fr_show,
    ctc_cli_app_fr_show_cmd,
    "show app flow-recorder status",
    "Show",
    CTC_CLI_APP_M_STR,
    "FLow recorder",
    "status")

{
    int32 ret = 0;
    ret = ctc_app_flow_recorder_show_status();
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CTC_E_NONE;
}
#endif

CTC_CLI(ctc_cli_app_ifa_set_en,
        ctc_cli_app_ifa_set_en_cmd,
        "app ifa (ifa-en) (enable|disable)",
        CTC_CLI_APP_M_STR,
        "Inband flow analyzer",
        "IFA Enable or Disable",
        "Enable",
        "Disable")
{
    int32 ret = CLI_SUCCESS;
    uint8 index = 0;
    uint8 enable = 0;

    index = CTC_CLI_GET_ARGC_INDEX("ifa-en");
    if (INDEX_VALID(index))
    {
        if (CLI_CLI_STR_EQUAL("enable", index + 1))
        {
            enable = 1;
        }
    }

    ret = ctc_app_ifa_set_en(g_api_ldev, enable);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_ifa_get_en,
        ctc_cli_app_ifa_get_en_cmd,
        "show app ifa (ifa-en)",
        "Show",
        CTC_CLI_APP_M_STR,
        "Inband flow analyzer",
        "IFA Enable or Disable")
{
    int32 ret = CLI_SUCCESS;
    uint8 enable = 0;

    ret = ctc_app_ifa_get_en(g_api_ldev, &enable);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    ctc_cli_out("ifa-en:%s\n", enable ? "enable" : "disable");

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_ifa_set_cfg,
        ctc_cli_app_ifa_set_cfg_cmd,
        "app ifa session ID node (none|initiator {gns GNS | max-length MAX_LEN | hop-limit HOP_LIMIT | log-percent LOG_PER | req-vec REQ_VEC|} |transit|terminate {nh-id NH_ID|} )",
        CTC_CLI_APP_M_STR,
        "Inband flow analyzer",
        "Session",
        "Session ID",
        "Node Type",
        "None Operation",
        "Initiator",
        "GNS",
        "GNS Value",
        "Max Length",
        "Max Length Value",
        "Hop Limit",
        "Hop Limit Value",
        "Log Percent",
        "Log Percent Value",
        "Request Vector",
        "Request Vector Value",
        "Transit",
        "Terminate",
        "Nexthop",
        "Nexthop ID")
{
    int32 ret = CLI_SUCCESS;
    uint8 index = 0;
    ctc_dtel_ifa_cfg_t ifa_cfg;

    sal_memset(&ifa_cfg, 0, sizeof(ctc_dtel_ifa_cfg_t));
    CTC_CLI_GET_UINT8("session id", ifa_cfg.session_id, argv[0]);

    if (CLI_CLI_STR_EQUAL("none", 1))
    {
        ifa_cfg.node = CTC_DTEL_IFA_NODE_NONE;
    }
    else if (CLI_CLI_STR_EQUAL("initiator", 1))
    {
        ifa_cfg.node = CTC_DTEL_IFA_NODE_INITIATOR;
        index = CTC_CLI_GET_ARGC_INDEX("gns");
        if (INDEX_VALID(index))
        {
            CTC_CLI_GET_UINT8("gns", ifa_cfg.gns, argv[index + 1]);
        }
        index = CTC_CLI_GET_ARGC_INDEX("max-length");
        if (INDEX_VALID(index))
        {
            CTC_CLI_GET_UINT8("max length", ifa_cfg.max_length, argv[index + 1]);
        }
        index = CTC_CLI_GET_ARGC_INDEX("hop-limit");
        if (INDEX_VALID(index))
        {
            CTC_CLI_GET_UINT8("hop limit", ifa_cfg.hop_limit, argv[index + 1]);
        }
        index = CTC_CLI_GET_ARGC_INDEX("log-percent");
        if (INDEX_VALID(index))
        {
            CTC_CLI_GET_UINT8("log percent", ifa_cfg.log_percent, argv[index + 1]);
        }
        index = CTC_CLI_GET_ARGC_INDEX("req-vec");
        if (INDEX_VALID(index))
        {
            CTC_CLI_GET_UINT8("reqest vector", ifa_cfg.req_vec, argv[index + 1]);
        }
    }
    else if (CLI_CLI_STR_EQUAL("transit", 1))
    {
        ifa_cfg.node = CTC_DTEL_IFA_NODE_TRANSIT;
    }
    else
    {
        ifa_cfg.node = CTC_DTEL_IFA_NODE_TERMINATE;
        index = CTC_CLI_GET_ARGC_INDEX("nh-id");
        if (INDEX_VALID(index))
        {
            CTC_CLI_GET_UINT32("nh id", ifa_cfg.nh_id, argv[index + 1]);
        }
    }

    ret = ctc_app_ifa_set_cfg(g_api_ldev, &ifa_cfg);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}


CTC_CLI(ctc_cli_app_ifa_get_cfg,
        ctc_cli_app_ifa_get_cfg_cmd,
        "show app ifa session ID",
        "Show",
        CTC_CLI_APP_M_STR,
        "Inband flow analyzer",
        "Session",
        "Session ID")
{
    int32 ret = CLI_SUCCESS;
    ctc_dtel_ifa_cfg_t ifa_cfg;

    sal_memset(&ifa_cfg, 0, sizeof(ctc_dtel_ifa_cfg_t));
    CTC_CLI_GET_UINT8("session id", ifa_cfg.session_id, argv[0]);

    ret = ctc_app_ifa_get_cfg(g_api_ldev, &ifa_cfg);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    switch (ifa_cfg.node)
    {
        case CTC_DTEL_IFA_NODE_NONE:
            ctc_cli_out("%-25s:%s\n", "session node", "none");
            break;
        case CTC_DTEL_IFA_NODE_INITIATOR:
            ctc_cli_out("%-25s:%s\n", "session node", "initiator");
            ctc_cli_out("%-25s:%d\n", "log percent", ifa_cfg.log_percent);
            ctc_cli_out("%-25s:%d\n", "GNS", ifa_cfg.gns);
            ctc_cli_out("%-25s:%d\n", "hop limit", ifa_cfg.hop_limit);
            ctc_cli_out("%-25s:%d\n", "max length", ifa_cfg.max_length);
            ctc_cli_out("%-25s:%d\n", "request vector", ifa_cfg.req_vec);
            break;
        case CTC_DTEL_IFA_NODE_TRANSIT:
            ctc_cli_out("%-25s:%s\n", "session node", "transit");
            break;
        case CTC_DTEL_IFA_NODE_TERMINATE:
            ctc_cli_out("%-25s:%s\n", "session node", "terminate");
            ctc_cli_out("%-25s:%u\n", "nh-id", ifa_cfg.nh_id);
            break;
        default:
            break;
    }

    return CLI_SUCCESS;
}


CTC_CLI(ctc_cli_app_tex_set,
        ctc_cli_app_tex_set_cmd,
        "app tex type (drop-event) (enable nh-id NH_ID | disable)",
        CTC_CLI_APP_M_STR,
        "Telemetry events export",
        "Export type",
        "Packet drop event",
        "Enable",
        "Nexthop Id",
        "Nexthop Id Value",
        "Disable")
{
    int32 ret = CLI_SUCCESS;
    uint32 nh_id = 0;

    if (CLI_CLI_STR_EQUAL("enable", 1))
    {
        CTC_CLI_GET_UINT32("nh id", nh_id, argv[3]);
    }
    else
    {
        nh_id = 0;
    }

    ret = ctc_app_tex_set_cfg(g_api_ldev, nh_id);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_tex_get,
        ctc_cli_app_tex_get_cmd,
        "show app tex type (drop-event)",
        "Show",
        CTC_CLI_APP_M_STR,
        "Telemetry event export",
        "Export type",
        "Packet drop event")
{
    int32 ret = CLI_SUCCESS;
    uint32 nh_id = 0;
    
    ret = ctc_app_tex_get_cfg(g_api_ldev, &nh_id);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("%-20s: %s\n", "enable", nh_id ? "TRUE" : "FALSE");
    if (nh_id)
    {
        ctc_cli_out("%-20s: %u\n", "nh-id", nh_id);
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_tsx_set,
        ctc_cli_app_tsx_set_cmd,
        "app tsx type (drop-stats | buffer-watermark | latency-watermark)\
        (enable | disable) (ports ("CTC_CLI_PORT_BITMAP_STR"|"CTC_CLI_PORT_BITMAP_ARRAY_STR") |) (interval INTERVAL |) (nh-id NH_ID |)",
        CTC_CLI_APP_M_STR,
        "Telemetry statistics export",
        "Export type",
        "Drop statistics",
        "Buffer watermark",
        "Latency watermark",
        "Enable",
        "Disable",
        "Ports",
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_DESC,
        CTC_CLI_PORT_BITMAP_VALUE_DESC,
        CTC_CLI_PORT_BITMAP_ARRAY_DESC,
        "Export interval",
        "Interval Value",
        "Nexthop Id",
        "Nexthop Id Value")
{
    int32 ret = CLI_SUCCESS;
    uint8 index = 0xFF;
    ctc_dtel_tsx_cfg_t tsx_cfg;
    uint32 max_num = CTC_PORT_BITMAP_IN_WORD;

    sal_memset(&tsx_cfg, 0, sizeof(ctc_dtel_tsx_cfg_t));
    if (CLI_CLI_STR_EQUAL("drop-stats", 0))
    {
        tsx_cfg.type = CTC_DTEL_TSX_DROP_STATS;
    }
    else if (CLI_CLI_STR_EQUAL("buffer-watermark", 0))
    {
        tsx_cfg.type = CTC_DTEL_TSX_BUFFER_WATERMARK;
    }
    else if (CLI_CLI_STR_EQUAL("latency-watermark", 0))
    {
        tsx_cfg.type = CTC_DTEL_TSX_LATENCY_WATERMARK;
    }
    else
    {
        return CLI_ERROR;
    }

    if (CLI_CLI_STR_EQUAL("enable", 1))
    {
        tsx_cfg.enable = 1;
    }
    else
    {
        tsx_cfg.enable = 0;
    }
    CTC_CLI_PORT_BITMAP_GET(tsx_cfg.port_bmp);
    index = CTC_CLI_GET_ARGC_INDEX("array-bmp");
    if(index != 0xFF)
    {
    	CTC_CLI_GET_UINT32_ARRAY("array-bmp", tsx_cfg.port_bmp, &max_num, argv[index + 1], ret);
    }

    index = CTC_CLI_GET_ARGC_INDEX("interval");
    if (index != 0xFF)
    {
        CTC_CLI_GET_UINT32("interval", tsx_cfg.interval, argv[index + 1]);
    }
    index = CTC_CLI_GET_ARGC_INDEX("nh-id");
    if (INDEX_VALID(index))
    {
        CTC_CLI_GET_UINT32("nh id", tsx_cfg.nh_id, argv[index + 1]);
    }
    
    ret = ctc_app_tsx_set_cfg(g_api_ldev, &tsx_cfg);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CLI_SUCCESS;
}


CTC_CLI(ctc_cli_app_tsx_get,
        ctc_cli_app_tsx_get_cmd,
        "show app tsx type (drop-stats  | buffer-watermark | latency-watermark)",
        "Show",
        CTC_CLI_APP_M_STR,
        "Telemetry statistics export",
        "Export type",
        "Drop statistics",
        "Buffer watermark",
        "Latency watermark")
{
    int32 ret = CLI_SUCCESS;
    uint32 idx = 0;
    ctc_dtel_tsx_cfg_t tsx_cfg;

    sal_memset(&tsx_cfg, 0, sizeof(ctc_dtel_tsx_cfg_t));

    if (CLI_CLI_STR_EQUAL("drop-stats", 0))
    {
        tsx_cfg.type = CTC_DTEL_TSX_DROP_STATS;
    }
    else if (CLI_CLI_STR_EQUAL("buffer-watermark", 0))
    {
        tsx_cfg.type = CTC_DTEL_TSX_BUFFER_WATERMARK;
    }
    else if (CLI_CLI_STR_EQUAL("latency-watermark", 0))
    {
        tsx_cfg.type = CTC_DTEL_TSX_LATENCY_WATERMARK;
    }
    else
    {
        return CLI_ERROR;
    }

    ret = ctc_app_tsx_get_cfg(g_api_ldev, &tsx_cfg);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("%-20s: %s\n", "enable", tsx_cfg.enable ? "TRUE" : "FALSE");
    if (tsx_cfg.enable)
    {
        ctc_cli_out("%-20s: %u\n","interval", tsx_cfg.interval);
        ctc_cli_out("%-20s: %u\n", "nh-id", tsx_cfg.nh_id);
        for (idx = 0; idx < CTC_PORT_BITMAP_IN_WORD; idx++)
        {
            if (tsx_cfg.port_bmp[idx])
            {
                ctc_cli_out("Port Bitmap [%d]: 0x%x\n",idx, tsx_cfg.port_bmp[idx]);
            }
        }
    }
    return CLI_SUCCESS;
}


CTC_CLI(ctc_cli_app_mox_set,
        ctc_cli_app_mox_set_cmd,
        "app tix type (ipfix) (enable nh-id NH_ID | disable)",
        CTC_CLI_APP_M_STR,
        "Telemetry informations export",
        "Export type",
        "Ipfix",
        "Enable",
        "Nexthop Id",
        "Nexthop Id Value",
        "Disable")
{
    int32 ret = CLI_SUCCESS;
    uint32 nh_id = 0;

    if (CLI_CLI_STR_EQUAL("enable", 1))
    {
        CTC_CLI_GET_UINT32("nh id", nh_id, argv[3]);
    }
    else
    {
        nh_id = 0;
    }

    ret = ctc_app_mox_set_cfg(g_api_ldev, nh_id);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_mox_get,
        ctc_cli_app_mox_get_cmd,
        "show app tix type ipfix",
        "Show",
        CTC_CLI_APP_M_STR,
        "Telemetry informations export",
        "Export type",
        "Ipfix")
{
    int32 ret = CLI_SUCCESS;
    uint8 enable = 0;

    ret = ctc_app_mox_get_cfg(g_api_ldev, &enable);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("%-20s: %s\n", "enable", enable ? "TRUE" : "FALSE");

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_set_switch_id,
        ctc_cli_app_set_switch_cmd,
        "app property (switch-id SW_ID)",
        CTC_CLI_APP_M_STR,
        "Property",
        "Switch id",
        "Switch id value"
        )
{
    int32 ret = 0;
    uint8 index = 0;
    uint32 value = 0;
    
    index = CTC_CLI_GET_ARGC_INDEX("switch-id");
    if (INDEX_VALID(index))
    {
        CTC_CLI_GET_INTEGER("switch-id", value, argv[index + 1]);
    }

    ret = ctc_app_set_switch_id(g_api_ldev, (void*)&value);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_get_switch_id,
        ctc_cli_app_get_switch_id_cmd,
        "show app property switch-id",
        "Show",
        CTC_CLI_APP_M_STR,
        "Property",
        "Switch id")
{
    int32 ret = 0;
    uint32 switch_id = 0;

    ret = ctc_app_get_switch_id(g_api_ldev, (void*)&switch_id);
    if (ret)
    {
        ctc_cli_out("%% %s\n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    ctc_cli_out("%-20s:0x%x\n", "switch-id", switch_id);

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_app_show_eunit_app_status,
        ctc_cli_app_show_eunit_app_status_cmd,
        "show app eunit ID status (app-id APP_ID)",
        "Show",
        CTC_CLI_APP_M_STR,
        "Eunit",
        "Eunit ID",
        "show eunit info",
        "app id",
        "APP ID")
{
    uint8 index = 0xFF;
    int32 ret = 0;
    uint8 app_id = 0;
    uint8 eunit_id = 0;
    
    CTC_CLI_GET_UINT8("eunit-id", eunit_id, argv[0]);

    index = CTC_CLI_GET_ARGC_INDEX("app-id");
    if (INDEX_VALID(index))
    {
        CTC_CLI_GET_UINT32("app-id", app_id, argv[index + 1]);
    }

    ret = ctc_app_show_eunit_app_status(g_api_ldev, eunit_id, app_id);
    if (ret)
    {
        ctc_cli_out("%% ret =%d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

int32
ctc_app_cli_init(void)
{
    install_element(CTC_SDK_MODE, &ctc_cli_app_packet_show_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_app_packet_print_rx_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_app_packet_create_socket_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_app_packet_destroy_socket_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_app_debug_on_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_app_debug_off_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_module_init_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_module_deinit_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_change_mem_profile_cmd);
#ifdef _SAL_LINUX_UM
    install_element(CTC_APP_MODE, &ctc_cli_app_packet_netif_rx_tx_cmd);
#endif

#ifdef CTC_PUMP
    install_element(CTC_APP_MODE, &ctc_cli_app_pump_init_deinit_cmd);
#endif
#ifdef CTC_APP_FLOW_RECORDER
    install_element(CTC_APP_MODE, &ctc_cli_app_fr_show_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_fr_init_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_fr_deinit_cmd);
#endif

    install_element(CTC_APP_MODE, &ctc_cli_app_ifa_set_en_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_ifa_get_en_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_ifa_set_cfg_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_ifa_get_cfg_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_tex_set_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_tex_get_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_tsx_set_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_tsx_get_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_mox_set_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_mox_get_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_set_switch_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_get_switch_id_cmd);
    install_element(CTC_APP_MODE, &ctc_cli_app_show_eunit_app_status_cmd);

    return CLI_SUCCESS;
}
